package com.ruoyi.pos.api.service.task.impl;

import com.ruoyi.common.enums.*;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.pos.api.dto.user.UserTeamDto;
import com.ruoyi.pos.api.service.common.ICommonService;
import com.ruoyi.pos.api.service.task.ITransFlowService;
import com.ruoyi.pos.api.utils.CommonUtils;
import com.ruoyi.pos.api.vo.user.UserTeamListVo;
import com.ruoyi.pos.web.domain.*;
import com.ruoyi.pos.web.mapper.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author luobo
 * @title: TransFlowServiceImpl
 * @projectName pos
 * @description: TODO
 * @date 2021-11-09 10:52:34
 */
@Service
public class TransFlowServiceImpl implements ITransFlowService {
    private static final Logger log = LoggerFactory.getLogger(TransFlowServiceImpl.class);
    @Autowired
    private TUserInfoMapper userInfoMapper;
    @Autowired
    private TUserDefaultInfoMapper userDefaultInfoMapper;
    @Autowired
    private TUserTeamInfoMapper userTeamInfoMapper;
    @Autowired
    private TGradeInfoMapper gradeInfoMapper;
    @Autowired
    private TGradeTypeInfoMapper gradeTypeInfoMapper;
    @Autowired
    private TTerminalInfoMapper terminalInfoMapper;
    @Autowired
    private TGoldDealSerialInfoMapper goldDealSerialInfoMapper;
    @Autowired
    private TGoldAwardSerialInfoMapper goldAwardSerialInfoMapper;
    @Autowired
    private TGoldInfoMapper goldInfoMapper;
    @Autowired
    private TTerminalBrandInfoMapper terminalBrandInfoMapper;
    @Autowired
    private TTerminalTransFlowInfoMapper terminalTransFlowInfoMapper;
    @Autowired
    private TTerminalTransFlowShareInfoMapper terminalTransFlowShareInfoMapper;
    @Autowired
    private TTerminalActivateSetInfoMapper terminalActivateSetInfoMapper;
    @Autowired
    private TStatisticInfoMapper statisticInfoMapper;
    @Autowired
    private TRebateSetInfoMapper rebateSetInfoMapper;

    @Autowired
    private ICommonService commonService;
    @Autowired
    private CommonUtils commonUtils; //公共业务处理类

    //查询未处理的临时表数据
    @Override
    public List<TTerminalTransFlowInfo> queryTransFlow() {
        TTerminalTransFlowInfo mapper = new TTerminalTransFlowInfo();
        mapper.setIsValid(YesOrNoEnums.YES.getCode());
        return terminalTransFlowInfoMapper.selectTTerminalTransFlowInfoList(mapper);
    }

    //根据交易流水处理本地业务逻辑
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void handleLocalTransLogic(TTerminalTransFlowInfo flow) throws Exception{
        BigDecimal transAmount = flow.getTransAmount().divide(new BigDecimal(100)); //将交易金额单位转化为元
        Date date = DateUtils.getNowDate();
        //根据sn号查询用户信息
        TTerminalInfo terminal = terminalInfoMapper.selectTTerminalInfoBySnCode(flow.getSnCode());
        if (null == terminal) {
            log.info("handleLocalTransLogic终端信息出错，snCode：" + flow.getSnCode());
            return;
        }
        if (StringUtils.isEmpty(terminal.getUserId())) {
            log.info("handleLocalTransLogic终端用户未进行实名认证，数据不做处理，终端号：" + terminal.getSnCode());
            return;
        }
        if (YesOrNoEnums.YES.getCode().equals(terminal.getBindingStatus())) { //说明终端还没有绑定，要进行绑定操作
            terminal.setBindingTime(date);
            terminal.setBindingStatus(YesOrNoEnums.NO.getCode());
        }
        TTerminalBrandInfo brand = terminalBrandInfoMapper.selectTTerminalBrandInfoById(terminal.getBrandId());
        if (null == brand) {
            log.info("handleLocalTransLogic终端品牌信息不能为空");
            return;
        }
        //查询配置信息
        TRebateSetInfo set = commonService.queryTRebateSetInfoVo();
        TUserInfo user = userInfoMapper.selectTUserInfoByUserId(terminal.getUserId());
        //更新用户累计交易额
        user.setTotalTransAmount(user.getTotalTransAmount().add(transAmount));
        userInfoMapper.updateTUserInfo(user);
        TUserInfo supUser = userInfoMapper.selectTUserInfoByUserId(user.getSuperiorUserId());
        TUserDefaultInfo defaultInfo = null;

        //插入一条统计数据，以天为单位、记录交易数，交易金额
        //一、记录统计数据----------------------------------------------atart（分品牌）
        log.info("记录统计数据-----------------------------------end");
        TStatisticInfo statistic = statisticInfoMapper.selectTStatisticInfoForCurrentDay(user.getUserId(), brand.getId());
        if (null == statistic) {
            statistic = commonUtils.generateStatisticInfo(user, DateUtils.getNowDate(), brand.getId());
            statisticInfoMapper.insertTStatisticInfo(statistic);
        }
        statistic.setMyTransMoney(statistic.getMyTransMoney().add(transAmount));
        statistic.setMyTransNum(statistic.getMyTransNum().add(BigDecimal.ONE));
        statisticInfoMapper.updateTStatisticInfo(statistic);
        log.info("记录统计数据-----------------------------------end");
        //记录统计数据----------------------------------------------end


        //二、根据用户累计交易额，计算是否需要升级----------------------------------------------------------start（不分品牌）
        //会员升级、-------------------------------------------参考终端绑定接口
        List<String> users = new ArrayList<String>();
        users.add(user.getUserId());
        statistic = statisticInfoMapper.selectTStatisticInfoByUserIds(users, "", "", "");
        BigDecimal userTotal = statistic.getMyTransMoney();
        TGradeInfo userGrade = gradeInfoMapper.selectTGradeInfoById(user.getGradeId());
        int currGradSort = userGrade.getSort();
        log.info("升级-----------------------------------当前会员等级{}", currGradSort);
        List<TGradeInfo> gradeList = gradeInfoMapper.selectTGradeInfoListBySort(currGradSort+""); //已按照sort进行排序
        TGradeInfo gradeCore = gradeInfoMapper.selectTGradeInfoList(new TGradeInfo())
                .stream()
                .max(Comparator.comparing(TGradeInfo::getSort))
                .get(); //取核心V9的等级，核心V9只能通过扫码得到，不能升级获取
        gradeList.stream().forEach(grade ->{
            if (grade.getSort() > currGradSort && grade.getSort() < gradeCore.getSort()) {
                if (userTotal.compareTo(grade.getBadSum()) > 0) { //说明终端交易额满足了升级条件
                    user.setGradeId(grade.getId());
                    userInfoMapper.updateTUserInfo(user);
                }
            }
        });
        log.info("升级-----------------------------------end");
        //根据用户累计交易额，计算是否需要升级----------------------------------------------------------end


        //三、终端激活-----------------------------------start（分品牌，区分终端）
        //终端达到一定交易额后，该终端激活，并返回【我的余额】-【商户收益】中相关收益信息、固定时间激活终端，用户获取积分、奖励金
        if (!"000000000".equals(flow.getAgentId())) { //说明不是初始化交易数据，需要将第三方推送过来的数据维护到终端
            terminal.setTerminalGmv(terminal.getTerminalGmv().add(transAmount));
            terminal.setTerminalNum(terminal.getTerminalNum().add(BigDecimal.ONE));
        }
        if (YesOrNoEnums.YES.getCode().equals(terminal.getActivateStatus())) { //说明是未激活
            log.info("终端激活-----------------------------------start");
            TTerminalActivateSetInfo activeMapper = new TTerminalActivateSetInfo();
            activeMapper.setBrandId(terminal.getBrandId());
            log.info("终端激活-----------------------------------终端品牌id：" + terminal.getBrandId());
            List<TTerminalActivateSetInfo> activeSet = terminalActivateSetInfoMapper.selectTTerminalActivateSetInfoList(activeMapper);
            TTerminalActivateSetInfo active = activeSet.get(0);
            if (terminal.getTerminalGmv().compareTo(active.getActiveAmount()) >= 0) { //说明交易额达到了激活条件
                log.info("终端激活-----------------------------------交易额达到了激活条件");
                //计算终端绑定时间
                //先查询该终端下的第一笔交易处理成功的时间，如果没有处理成功过的数据，则默认为当前时间
                Date minDate = terminalTransFlowInfoMapper.selectTTerminalTransFlowInfoForMinTime(terminal.getSnCode());
                if (null == minDate) { //说明当前是第一笔交易，之前还没有处理成功过，则默认为当前时间
                    minDate = date;
                }
                Long days = DateUtils.getDatePoorHour(date, minDate);
                if (days < Long.valueOf(active.getActiveTime())) { //说明是在固定时间内激活（从第一笔交易处理成功时间开始算）
                    log.info("终端激活-----------------------------------说明是在固定时间内激活");
                    //更新激活时间、激活状态
                    terminal.setActivateTime(date);
                    terminal.setActivateStatus(YesOrNoEnums.NO.getCode());
                    //terminalInfoMapper.updateTTerminalInfo(terminal);
                    //计算激活奖励
                    List<TGradeInfo> gradeList1 = gradeInfoMapper.selectTGradeInfoList(new TGradeInfo()).stream().sorted(Comparator.comparing(TGradeInfo::getSort).reversed()).collect(Collectors.toList());
                    TGradeInfo gradeMin = gradeList1.stream().min(Comparator.comparing(TGradeInfo::getSort)).get();
                    //写交易流水表(积分)
                    TUserDefaultInfo defaultInfoJifen = commonUtils.generateTUserDefaultInfo(
                            user.getUserId(),
                            terminal.getBrandId(),
                            TransTypeEnum.JIFEN.getCode(),
                            TransOperTypeEnum.JIFEN_2001.getCode(),
                            active.getAwardIntegral(),
                            "",
                            user.getUserId(),
                            null,
                            terminal.getSnCode(),
                            transAmount);
                    //写交易流水表(余额)
                    TUserDefaultInfo defaultInfoYue = commonUtils.generateTUserDefaultInfo(
                            user.getUserId(),
                            terminal.getBrandId(),
                            TransTypeEnum.YUE.getCode(),
                            TransOperTypeEnum.YUE_1004.getCode(),
                            active.getAwardCash(),
                            "",
                            user.getUserId(),
                            null,
                            terminal.getSnCode(),
                            transAmount);
                    log.info(gradeMin.getId() + "排查生产环境V0用户------test----------" + user.getGradeId());
                    if (gradeMin.getId().equals(user.getGradeId())) { //如果用户等级为V0，奖励由上级中第一个不是V0的人获取
                        log.info("排查生产环境V0用户----------------1");
                        //获取上级团队中第一个不是V0的用户
                        TUserInfo firstSupUser = new TUserInfo();
                        queryFirstSupUserForActive(user, firstSupUser);
                        if (StringUtils.isNotEmpty(firstSupUser.getUserId())) {
                            log.info("排查生产环境V0用户---------------2");
                            defaultInfoJifen.setUserId(firstSupUser.getUserId());
                            defaultInfoJifen.setUpdateUserId(firstSupUser.getUserId());
                            defaultInfoYue.setUserId(firstSupUser.getUserId());
                            defaultInfoYue.setUpdateUserId(firstSupUser.getUserId());
                            firstSupUser.setIntegralSum(firstSupUser.getIntegralSum().add(active.getAwardIntegral()));
                            firstSupUser.setBalanceSum(firstSupUser.getBalanceSum().add(active.getAwardCash()));
                            userInfoMapper.updateTUserInfo(firstSupUser);
                        } else {
                            log.info("当前用户等级为：" + user.getGradeId() + "，递归查询获取的上级等级不为0的用户为空");
                        }
                    } else { //如果用户等级不为V0，奖励由自己获取
                        user.setIntegralSum(user.getIntegralSum().add(active.getAwardIntegral()));
                        user.setBalanceSum(user.getBalanceSum().add(active.getAwardCash()));
                        userInfoMapper.updateTUserInfo(user);
                    }
                    //查询上级中是核心V9的人，获取激活办公补贴
                    userDefaultInfoMapper.insertTUserDefaultInfo(defaultInfoJifen);
                    userDefaultInfoMapper.insertTUserDefaultInfo(defaultInfoYue);

                    //上级中存在核心V9的用户，则改核心V9用户获取对应的激活办公补贴
                    //递归查询上级用户中，用户等级为核心V9的用户
                    //写交易流水表(余额)
                    TUserDefaultInfo defaultInfoCore = commonUtils.generateTUserDefaultInfo(
                            user.getUserId(),
                            terminal.getBrandId(),
                            TransTypeEnum.YUE.getCode(),
                            TransOperTypeEnum.YUE_1009.getCode(),
                            active.getWorkSubsidy(),
                            "",
                            user.getSuperiorUserId(),
                            null,
                            terminal.getSnCode(),
                            transAmount);
                    log.info("激活获取办公补贴-------------------开始");
                    log.info("激活获取办公补贴-------------------当前用户会员等级：" + user.getGradeId());
                    if (user.getGradeId().equalsIgnoreCase(gradeCore.getId())) { //说明自己是核心V9
                        log.info("激活获取办公补贴-------------------自己是核心V9：" + user.getUserName() + "---" + user.getUserId());
                        user.setBalanceSum(user.getBalanceSum().add(active.getWorkSubsidy()));
                        userInfoMapper.updateTUserInfo(user);
                    } else {
                        TUserInfo coreSupUser = new TUserInfo();
                        //递归查询上级中的核心V9成员
                        queryFirstSupUserForCore(user, coreSupUser, gradeCore);
                        log.info("激活获取办公补贴-------------------上级核心V9用户：" + coreSupUser.getUserName() + "---" + coreSupUser.getUserId());
                        defaultInfoCore.setUserId(coreSupUser.getUserId());
                        defaultInfoCore.setUpdateUserId(coreSupUser.getUserId());
                        coreSupUser.setBalanceSum(coreSupUser.getBalanceSum().add(active.getWorkSubsidy()));
                        userInfoMapper.updateTUserInfo(coreSupUser);
                    }
                    userDefaultInfoMapper.insertTUserDefaultInfo(defaultInfoCore);
                    log.info("激活获取办公补贴-------------------结束");
                }
            }
            log.info("终端激活-----------------------------------end");
        }
        //终端激活-----------------------------------end


        //四、计算分润---------------------------------------------------start（不分品牌）
        //如果该笔交易额达到固定条件，进行分润计算（直属上级收益，团队上级收益）
        if (StringUtils.isNotEmpty(user.getSuperiorUserId())) { //说明有上级存在，有上级才会存在分润
            log.info("分润-----------------------------------start");
            //查询当前用户最新的会员等级
            userGrade = gradeInfoMapper.selectTGradeInfoById(user.getGradeId());
            TGradeTypeInfo typeMapper = new TGradeTypeInfo();
            //根据不同的交易类型，分别查询对应的分润逻辑
            if (PayTypeEnum.getSwipeList().contains(flow.getPayType())) { //刷卡
                if ("1".equals(flow.getCardType())) { //贷记卡消费
                    typeMapper.setGradeName("刷卡");
                }
            } else if (PayTypeEnum.getScanCodeList().contains(flow.getPayType())) { //扫码
                if (transAmount.compareTo(set.getBillAmount()) >= 0) { //大于等于某个金额
                    typeMapper.setGradeName("扫码大于");
                } else { //小于某个金额
                    typeMapper.setGradeName("扫码小于");
                }
            } else { //闪付
                if ("6".equals(flow.getCardType())) { //云闪付消费
                    typeMapper.setGradeName("闪付");
                }
            }
            log.info("交易类型+"+typeMapper.getGradeName());
            TGradeTypeInfo gradeTypeP = gradeTypeInfoMapper.selectTGradeTypeInfoList(typeMapper).get(0);
            typeMapper = new TGradeTypeInfo();
            log.info("上级会员等级+"+gradeTypeP.getId());
            typeMapper.setParentId(gradeTypeP.getId());
            List<TGradeTypeInfo> gradeTypeList = gradeTypeInfoMapper.selectTGradeTypeInfoList(typeMapper);
            log.info("分润-----------------------------------代理商上级产生跨级分润");
            int userGradeSort = userGrade.getSort();
            //先给自己分润
            List<TGradeTypeInfo> ownList = gradeTypeList.stream().filter(bean ->bean.getSort() <= userGradeSort).collect(Collectors.toList());
            if (null != ownList && ownList.size() > 0) {
                BigDecimal own = BigDecimal.ZERO;
                for (TGradeTypeInfo type : ownList) {
                    own = own.add(type.getShareProfitBalance());
                }
                BigDecimal fenrun = transAmount.multiply(own).setScale(2, BigDecimal.ROUND_DOWN);
                user.setBalanceSum(user.getBalanceSum().add(fenrun));
                userInfoMapper.updateTUserInfo(user);
                //插入余额交易流水记录表
                TUserDefaultInfo defaultInfoThis1 = commonUtils.generateTUserDefaultInfo(
                        user.getUserId(),
                        terminal.getBrandId(),
                        TransTypeEnum.YUE.getCode(),
                        TransOperTypeEnum.YUE_1006.getCode(),
                        fenrun,
                        flow.getOrderId(), //默认存储的是平台订单号，如果是分润记录，则存储的是第三方的交易流水号，用于关联该笔交易产生的分润
                        user.getUserId(),
                        null,
                        terminal.getSnCode(),
                        transAmount);
                userDefaultInfoMapper.insertTUserDefaultInfo(defaultInfoThis1);
                //插入分润记录
                TTerminalTransFlowShareInfo share1 = TTerminalTransFlowShareInfo.builder()
                        .shareAmount(fenrun)
                        .shareDiff(own)
                        .shareUserId(user.getUserId())
                        .id(IdUtils.simpleUUID())
                        .flowId(flow.getId())
                        .build();
                share1.setCreateTime(DateUtils.getNowDate());
                terminalTransFlowShareInfoMapper.insertTTerminalTransFlowShareInfo(share1);
            }
            //再给自己的团队上级进行分润，查询比当前用户等级高的会员级别列表
            //先递归查询自己的所有上级中，能够获取分润的用户集合
            if(gradeList.size() > 0){
                TGradeInfo gradeMax = gradeList.stream().max(Comparator.comparing(TGradeInfo::getSort)).get();
                List<SupUserBean> supUSerList = new ArrayList<SupUserBean>();
                querySupUserForShare(user, Integer.valueOf(user.getGradeId()) + 1, Integer.valueOf(gradeMax.getId()), supUSerList, gradeTypeList);
                Optional.ofNullable(supUSerList).ifPresent(list ->{
                    list.stream().forEach(bean ->{
                        BigDecimal fenrun = transAmount.multiply(bean.getProportion()).setScale(2, BigDecimal.ROUND_DOWN);
                        TUserInfo teamUser = userInfoMapper.selectTUserInfoByUserId(bean.getUserId());
                        teamUser.setBalanceSum(teamUser.getBalanceSum().add(fenrun));
                        userInfoMapper.updateTUserInfo(teamUser);
                        //插入余额交易流水记录表
                        TUserDefaultInfo defaultInfoThis = commonUtils.generateTUserDefaultInfo(
                                bean.getUserId(),
                                terminal.getBrandId(),
                                TransTypeEnum.YUE.getCode(),
                                TransOperTypeEnum.YUE_1006.getCode(),
                                fenrun,
                                flow.getOrderId(), //默认存储的是平台订单号，如果是分润记录，则存储的是第三方的交易流水号，用于关联该笔交易产生的分润
                                user.getUserId(),
                                null,
                                terminal.getSnCode(),
                                transAmount);
                        userDefaultInfoMapper.insertTUserDefaultInfo(defaultInfoThis);
                        //插入分润记录
                        TTerminalTransFlowShareInfo share = TTerminalTransFlowShareInfo.builder()
                                .shareAmount(fenrun)
                                .shareDiff(bean.getProportion())
                                .shareUserId(bean.getUserId())
                                .id(IdUtils.simpleUUID())
                                .flowId(flow.getId())
                                .build();
                        share.setCreateTime(DateUtils.getNowDate());
                        terminalTransFlowShareInfoMapper.insertTTerminalTransFlowShareInfo(share);
                    });
                });
            }
        }
        log.info("分润-----------------------------------end");
        //计算分润--------------------------------------------------end


        //五、根据用户累计交易额，发放序列号----------------------------------------------------------start（不分品牌，阶段性分发）
        //userTotal 用户总交易额
        //交易金序列号、更新用户表交易金序列号个数
        log.info("序列号--------------------当前交易额" + userTotal);
        BigDecimal userDeal = set.getUserDeal(); //发放交易金序列号条件
        log.info("序列号--------------------当前交易金序列号发放条件" + userDeal);
        if (userTotal.compareTo(userDeal) >= 0) { //用户累计交易额大于等于平台配置的发放交易金序列号额度
            log.info("序列号-----------------------------------发放交易金序列号");
            TUserInfo newUser = userInfoMapper.selectTUserInfoByUserId(user.getUserId());
            recursiveProcessDealSerial(newUser, userDeal, userTotal, terminal.getBrandId(), date, terminal.getSnCode(), transAmount);
        }
        //奖励金序列号、更新用户表奖励金序列号个数
        BigDecimal userAward = set.getUserAward(); //发放奖励金序列号条件
        log.info("序列号--------------------当前奖励金序列号发放条件" + userAward);
        if (userTotal.compareTo(userAward) >= 0) { //用户累计交易额大于等于平台配置的发放交易金序列号额度
            log.info("序列号-----------------------------------发放奖励金序列号");
            TUserInfo newUser = userInfoMapper.selectTUserInfoByUserId(user.getUserId());
            recursiveProcessAwardSerial(newUser, userAward, userTotal, terminal.getBrandId(), date, terminal.getSnCode(), transAmount);
        }
        //根据用户累计交易额，发放序列号----------------------------------------------------------end


        //六、根据平台累计交易额，发放金币给最小的序列号----------------------------------------------------------start（不分品牌，阶段性分发）
        statistic = statisticInfoMapper.selectTStatisticInfoForTotal(); //获取平台累计交易额
        //处理交易金金币发放
        log.info("金币-----------------------------------发放交易金金币");
        handleDealGoldSend(statistic.getMyTransMoney(), set, terminal.getBrandId(), date, terminal.getSnCode(), transAmount);
        //处理奖励金金币发放
        log.info("金币-----------------------------------发放奖励金金币");
        handleAwardGoldSend(statistic.getMyTransMoney(), set, terminal.getBrandId(), date, terminal.getSnCode(), transAmount);
        //根据平台累计交易额，发放金币给最小的序列号----------------------------------------------------------end

        //统计累计交易额，计算商户收益，需判断配置表当前序列号是否已发放

        //处理成功后，将临时表数据置为无效
        flow.setIsValid(YesOrNoEnums.NO.getCode());
        flow.setHandleStaus(HandleStausEnum.HAS_HANDLE.getCode());
        flow.setHandleResult("处理成功");
        terminalTransFlowInfoMapper.updateTTerminalTransFlowInfo(flow);
        terminalInfoMapper.updateTTerminalInfo(terminal);
        log.info("第三方交易流水处理完毕-----------------------------------over");
    }

    //递归处理用户阶段性发放交易金逻辑
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void recursiveProcessDealSerial(TUserInfo user, BigDecimal userDeal, BigDecimal userTotal, String brandId, Date date, String snCode, BigDecimal transAmount) throws Exception {
        if (userTotal.subtract(user.getDealAmountHasSend()).compareTo(userDeal) >= 0) {
            //生成序列号记录
            TGoldDealSerialInfo serialNoInfo = goldDealSerialInfoMapper.queryDealAllMax(); //先查询最大的序列号
            if (null == serialNoInfo) {
                serialNoInfo = new TGoldDealSerialInfo();
                serialNoInfo.setSerialNo(0L);
            }
            TGoldDealSerialInfo deal = new TGoldDealSerialInfo();
            deal.setUserId(user.getUserId());
            deal.setExchange(YesOrNoEnums.NO.getCode());
            deal.setCreateTime(date);
            deal.setSerialNo(serialNoInfo.getSerialNo() + 1);
            goldDealSerialInfoMapper.insertTGoldDealSerialInfo(deal);
            //插入交易流水记录表
            TUserDefaultInfo defaultInfo = commonUtils.generateTUserDefaultInfo(
                    user.getUserId(),
                    brandId,
                    TransTypeEnum.JIAOYIJIN.getCode(),
                    TransOperTypeEnum.JIAOYIJIN_4001.getCode(),
                    BigDecimal.ONE,
                    "",
                    "",
                    deal.getId(),
                    snCode,
                    transAmount);
            userDefaultInfoMapper.insertTUserDefaultInfo(defaultInfo);
            //更新用户表的交易金序列号个数
            user.setDealGoldMark(user.getDealGoldMark().add(BigDecimal.ONE));
            user.setDealAmountHasSend(user.getDealAmountHasSend().add(userDeal));
            userInfoMapper.updateTUserInfo(user);
            recursiveProcessDealSerial(user, userDeal, userTotal, brandId, date, snCode, transAmount);
        } else {
            return;
        }
    }

    //递归处理用户阶段性发放奖励金逻辑
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void recursiveProcessAwardSerial(TUserInfo user, BigDecimal userAward, BigDecimal userTotal, String brandId, Date date, String snCode, BigDecimal transAmount) throws Exception {
        if (userTotal.subtract(user.getAwardAmountHasSend()).compareTo(userAward) >= 0) {
            //生成序列号记录
            TGoldAwardSerialInfo serialNoInfo = goldAwardSerialInfoMapper.queryAwardAllMax(); //先查询最大的序列号
            if (null == serialNoInfo) {
                serialNoInfo = new TGoldAwardSerialInfo();
                serialNoInfo.setSerialNo(0L);
            }
            TGoldAwardSerialInfo award = new TGoldAwardSerialInfo();
            award.setUserId(user.getUserId());
            award.setExchange(YesOrNoEnums.NO.getCode());
            award.setCreateTime(date);
            award.setSerialNo(serialNoInfo.getSerialNo() + 1);
            goldAwardSerialInfoMapper.insertTGoldAwardSerialInfo(award);
            //插入交易流水记录表
            TUserDefaultInfo defaultInfo = commonUtils.generateTUserDefaultInfo(
                    user.getUserId(),
                    brandId,
                    TransTypeEnum.JIANGLIJIN.getCode(),
                    TransOperTypeEnum.JIANGLIJIN_5001.getCode(),
                    BigDecimal.ONE,
                    "",
                    "",
                    award.getId(),
                    snCode,
                    transAmount);
            userDefaultInfoMapper.insertTUserDefaultInfo(defaultInfo);
            //更新用户表的交易金序列号个数
            user.setAwardGoldMark(user.getAwardGoldMark().add(BigDecimal.ONE));
            user.setAwardAmountHasSend(user.getAwardAmountHasSend().add(userAward));
            userInfoMapper.updateTUserInfo(user);
            recursiveProcessAwardSerial(user, userAward, userTotal, brandId, date, snCode, transAmount);
        } else {
            return;
        }
    }

    /*public static void main(String[] args) {
        BigDecimal a = new BigDecimal(1126700);
        BigDecimal b = new BigDecimal(300000);
        int issNum = a.divideAndRemainder(b)[0].intValue();
        System.out.println(a.divideAndRemainder(b));
        List<TGoldDealSerialInfo> dealList = new ArrayList<TGoldDealSerialInfo>();
        TGoldDealSerialInfo deal = new TGoldDealSerialInfo();
        deal.setId(1L);
        dealList.add(deal);
        deal = new TGoldDealSerialInfo();
        deal.setId(2L);
        dealList.add(deal);
        deal = new TGoldDealSerialInfo();
        deal.setId(3L);
        dealList.add(deal);
        deal = new TGoldDealSerialInfo();
        deal.setId(4L);
        dealList.add(deal);
        deal = new TGoldDealSerialInfo();
        deal.setId(5L);
        dealList.add(deal);
        deal = new TGoldDealSerialInfo();
        deal.setId(6L);
        dealList.add(deal);
        deal = new TGoldDealSerialInfo();
        deal.setId(7L);
        dealList.add(deal);
        deal = new TGoldDealSerialInfo();
        deal.setId(8L);
        dealList.add(deal);
        for (int i = 1; i <= issNum; i++) {
            System.out.println("----------------" + (i - 1) + "..." + dealList.get(i - 1).getId());
        }
    }*/

    //处理交易金金币发放
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void handleDealGoldSend(BigDecimal platTotal, TRebateSetInfo set, String brandId, Date date, String snCode, BigDecimal transAmount) throws Exception {
        //交易金金币，查询未兑换交易金序列号
        BigDecimal platformDeal = set.getPlatformDeal(); //平台配置的阶段性需要发放金额
        BigDecimal dealGold = set.getDealGold(); //平台配置的阶段性需要发放金额
        BigDecimal platformDealHasSend = set.getPlatformDealHasSend(); //平台已发放过金币的额度
        BigDecimal thisSend = platTotal.subtract(platformDealHasSend); //总交易额减去已发放的，等于这次需要发放的金额
        log.info("当笔交易需要发放的交易金金币，当前这笔交易总额：" + thisSend + "，平台阶段性需要发放的金额：" + platformDeal);
        int issNum = thisSend.divideAndRemainder(platformDeal)[0].intValue(); //需要发放的次数
        log.info("当笔交易需要发放的交易金金币个数：" + issNum);
        TGoldDealSerialInfo dealMapper = new TGoldDealSerialInfo();
        dealMapper.setExchange(YesOrNoEnums.NO.getCode());
        List<TGoldDealSerialInfo> dealList = goldDealSerialInfoMapper.selectTGoldDealSerialInfoList2(dealMapper); //获取交易金序号列表
        TGoldInfo gold = null;
        for (int i = 1; i <= issNum; i++) {
            //发放金币，并累加已发放的额度
            log.info("当笔交易需要发放的交易金金币个数，现在是第：" + i + "个");
            platformDealHasSend = platformDealHasSend.add(platformDeal);
            if (null != dealList && dealList.size() > 0) {
                log.info("当笔交易需要发放的交易金金币个数，现在是第：" + i + "个，实际发放");
                //获取未兑换的最小的交易金序列号
                TGoldDealSerialInfo minDeal = dealList.get(i - 1);
                minDeal.setExchange(YesOrNoEnums.YES.getCode());
                minDeal.setExchangeTime(date);
                minDeal.setAmount(dealGold);
                goldDealSerialInfoMapper.updateTGoldDealSerialInfo(minDeal);
                //插入余额交易流水记录表
                TUserDefaultInfo defaultInfo = commonUtils.generateTUserDefaultInfo(
                        minDeal.getUserId(),
                        brandId,
                        TransTypeEnum.JIAOYIJIN.getCode(),
                        TransOperTypeEnum.JIAOYIJIN_4004.getCode(),
                        BigDecimal.ZERO.subtract(BigDecimal.ONE),
                        "",
                        "",
                        minDeal.getId(),
                        snCode,
                        transAmount);
                defaultInfo.setGoldType("1"); //金币类型
                userDefaultInfoMapper.insertTUserDefaultInfo(defaultInfo);
                for (int n = 0; n < dealGold.intValue(); n++) {
                    gold = new TGoldInfo();
                    gold.setUserId(minDeal.getUserId());
                    gold.setCreateTime(date);
                    gold.setSerialId(minDeal.getId());
                    gold.setSerialType("1");
                    gold.setExchange(YesOrNoEnums.NO.getCode());
                    goldInfoMapper.insertTGoldInfo(gold);
                }
                TUserInfo dealUser = userInfoMapper.selectTUserInfoByUserId(minDeal.getUserId());
                dealUser.setGoldSum(dealUser.getGoldSum().add(dealGold));
                userInfoMapper.updateTUserInfo(dealUser);
                //插入金币交易流水记录表
                defaultInfo = commonUtils.generateTUserDefaultInfo(
                        dealUser.getUserId(),
                        brandId,
                        TransTypeEnum.JINBI.getCode(),
                        TransOperTypeEnum.JINBI_3001.getCode(),
                        dealGold,
                        "",
                        "",
                        minDeal.getId(),
                        snCode,
                        transAmount);
                defaultInfo.setGoldType("1"); //金币类型
                userDefaultInfoMapper.insertTUserDefaultInfo(defaultInfo);
            }
        }
        set.setPlatformDealHasSend(set.getPlatformDealHasSend().add(platformDeal.multiply(new BigDecimal(issNum))));
        rebateSetInfoMapper.updateTRebateSetInfo(set); //更新配置表数据
    }

    //处理奖励金金币发放
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void handleAwardGoldSend(BigDecimal platTotal, TRebateSetInfo set, String brandId, Date date, String snCode, BigDecimal transAmount) throws Exception {
        //奖励金金币，查询未兑换奖励金序列号
        BigDecimal platformAward = set.getPlatformAward(); //平台配置的阶段性需要发放金额
        BigDecimal awardGold = set.getAwardGold(); //平台配置的阶段性需要发放金额
        BigDecimal platformAwardHasSend = set.getPlatformAwardHasSend(); //平台已发放过金币的额度
        BigDecimal thisSend = platTotal.subtract(platformAwardHasSend); //总交易额减去已发放的，等于这次需要发放的金额
        int issNum = thisSend.divideAndRemainder(platformAward)[0].intValue(); //需要发放的次数
        log.info("当笔交易需要发放的奖励金金币个数：" + issNum);
        TGoldAwardSerialInfo awardMapper = new TGoldAwardSerialInfo();
        awardMapper.setExchange(YesOrNoEnums.NO.getCode());
        List<TGoldAwardSerialInfo> awardList = goldAwardSerialInfoMapper.selectTGoldAwardSerialInfoList2(awardMapper); //获取奖励金序号列表
        TGoldInfo gold = null;
        for (int i = 1; i <= issNum; i++) {
            //发放金币，并累加已发放的额度
            log.info("当笔交易需要发放的奖励金金币个数，现在是第：" + i + "个");
            platformAwardHasSend = platformAwardHasSend.add(platformAward);
            if (null != awardList && awardList.size() > 0) {
                log.info("当笔交易需要发放的奖励金金币个数，现在是第：" + i + "个，实际发放");
                //获取未兑换的最小的交易金序列号
                TGoldAwardSerialInfo minAward = awardList.get(i - 1);
                minAward.setExchange(YesOrNoEnums.YES.getCode());
                minAward.setExchangeTime(date);
                minAward.setAmount(awardGold);
                goldAwardSerialInfoMapper.updateTGoldAwardSerialInfo(minAward);
                TUserDefaultInfo defaultInfo = commonUtils.generateTUserDefaultInfo(
                        minAward.getUserId(),
                        brandId,
                        TransTypeEnum.JIANGLIJIN.getCode(),
                        TransOperTypeEnum.JIANGLIJIN_5004.getCode(),
                        BigDecimal.ZERO.subtract(BigDecimal.ONE),
                        "",
                        "",
                        minAward.getId(),
                        snCode,
                        transAmount);
                defaultInfo.setGoldType("2"); //金币类型
                userDefaultInfoMapper.insertTUserDefaultInfo(defaultInfo);
                for (int n = 0; n < awardGold.intValue(); n++) {
                    gold = new TGoldInfo();
                    gold.setUserId(minAward.getUserId());
                    gold.setCreateTime(date);
                    gold.setSerialId(minAward.getId());
                    gold.setSerialType("2");
                    gold.setExchange(YesOrNoEnums.NO.getCode());
                    goldInfoMapper.insertTGoldInfo(gold);
                }
                TUserInfo awardUser = userInfoMapper.selectTUserInfoByUserId(minAward.getUserId());
                awardUser.setGoldSum(awardUser.getGoldSum().add(awardGold));
                userInfoMapper.updateTUserInfo(awardUser);
                //插入金币交易流水记录表
                defaultInfo = commonUtils.generateTUserDefaultInfo(
                        awardUser.getUserId(),
                        brandId,
                        TransTypeEnum.JINBI.getCode(),
                        TransOperTypeEnum.JINBI_3001.getCode(),
                        awardGold,
                        "",
                        "",
                        minAward.getId(),
                        snCode,
                        transAmount);
                defaultInfo.setGoldType("2"); //金币类型
                userDefaultInfoMapper.insertTUserDefaultInfo(defaultInfo);
            }
        }
        set.setPlatformAwardHasSend(set.getPlatformAwardHasSend().add(platformAward.multiply(new BigDecimal(issNum))));
        rebateSetInfoMapper.updateTRebateSetInfo(set); //更新配置表数据
    }

    //递归查找当前用户所有可以进行分润的上级
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void querySupUserForShare(TUserInfo user, int nextGradeId, int maxGradeId, List<SupUserBean> list, List<TGradeTypeInfo> gradeTypeList) throws Exception {
        //log.info(user.getUserName()+"======"+user.getGradeId() + "-------------------------" + nextGradeId + "--------0--------" + maxGradeId);
        TUserInfo supUser = userInfoMapper.selectTUserInfoByUserId(user.getSuperiorUserId());
        TGradeInfo supUserGrade = gradeInfoMapper.selectTGradeInfoById(supUser.getGradeId());
        if (Integer.valueOf(supUserGrade.getId()) == maxGradeId) { //核心V9，不再继续往上找
            SupUserBean bean = SupUserBean.builder().build();
            bean.setUserId(supUser.getUserId());
            BigDecimal proportion = BigDecimal.ZERO;
            for (TGradeTypeInfo type : gradeTypeList) {
                if (Integer.valueOf(type.getGradeId()) >= nextGradeId) {
                    proportion = proportion.add(type.getShareProfitBalance());
                }
            }
            bean.setProportion(proportion);
            list.add(bean);
            return;
        } else {
            //log.info(user.getUserName()+"===1===");
            if (Integer.valueOf(supUserGrade.getId()) >= nextGradeId) {
                //log.info(user.getUserName()+"===2===");
                SupUserBean bean = SupUserBean.builder().build();
                bean.setUserId(supUser.getUserId());
                BigDecimal proportion = BigDecimal.ZERO;
                for (TGradeTypeInfo type : gradeTypeList) {
                    if (Integer.valueOf(type.getGradeId()) >= nextGradeId && Integer.valueOf(type.getGradeId()) <= Integer.valueOf(supUser.getGradeId())) {
                        proportion = proportion.add(type.getShareProfitBalance());
                    }
                }
                bean.setProportion(proportion);
                list.add(bean);
                if (Integer.valueOf(supUserGrade.getId()) == maxGradeId) {
                    return;
                }
                querySupUserForShare(supUser, Integer.valueOf(supUserGrade.getId()) + 1, maxGradeId, list, gradeTypeList);
            } else {
                //log.info(user.getUserName()+"===3===");
                querySupUserForShare(supUser, nextGradeId, maxGradeId, list, gradeTypeList);
            }
        }
    }

    //递归查找当前用户中第一个比自己等级高的用户
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void queryFirstSupUserForActive(TUserInfo user, TUserInfo firstSupUser) throws Exception {
        TUserInfo supUser = userInfoMapper.selectTUserInfoByUserId(user.getSuperiorUserId());
        if (Integer.valueOf(supUser.getGradeId()) > Integer.valueOf(user.getGradeId())) {
            BeanUtils.copyProperties(supUser, firstSupUser);
            return;
        } else {
            queryFirstSupUserForActive(supUser, firstSupUser);
        }
    }

    //递归查找当前用户中第一个核心V9的用户
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void queryFirstSupUserForCore(TUserInfo user, TUserInfo coreSupUser, TGradeInfo gradeCore) throws Exception {
        TUserInfo supUser = userInfoMapper.selectTUserInfoByUserId(user.getSuperiorUserId());
        if (supUser.getGradeId().equalsIgnoreCase(gradeCore.getId())) { //说明是核心V9的用户
            BeanUtils.copyProperties(supUser, coreSupUser);
            return;
        } else {
            queryFirstSupUserForCore(supUser, coreSupUser, gradeCore);
        }
    }























}
